package com.zx1316.javadoudizhuserver;

import javafx.application.Platform;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Random;

public class GameThread extends Thread {
    //S黑桃 H红桃 C梅花 D方块
    public static final String[] INIT_CARD = {"JB", "JS", "S2", "H2", "C2", "D2", "SA", "HA", "CA", "DA",
            "SK", "HK", "CK", "DK", "SQ", "HQ", "CQ", "DQ", "SJ", "HJ", "CJ", "DJ", "ST", "HT", "CT", "DT",
            "S9", "H9", "C9", "D9", "S8", "H8", "C8", "D8", "S7", "H7", "C7", "D7", "S6", "H6", "C6", "D6",
            "S5", "H5", "C5", "D5", "S4", "H4", "C4", "D4", "S3", "H3", "C3", "D3"};
    private final Random RANDOM = new Random();
    private final Object LOCK;
    private final Server SERVER;
    private final Controller CONTROLLER;
    private final ArrayList<ArrayList<Card>> CARDS_LIST = new ArrayList<>();
    private final ArrayList<ArrayList<String>> RECORDS = new ArrayList<>();
    private final String[] PLAYER_LIST = new String[3];
    private final int[] SCORES = {0, 0, 0};
    private int[] needDouble;
    private int points;
    private int waitingFor;
    private int rounds = 1;
    private boolean isPause;
    private boolean isInGame;

    public GameThread(Server server, Controller controller, Object lock) {
        this.CONTROLLER = controller;
        this.LOCK = lock;
        this.SERVER = server;
        for (int i = 0; i < 3; i++) {
            CARDS_LIST.add(new ArrayList<>());
            RECORDS.add(new ArrayList<>());
        }
    }

    @Override
    public void run() {
        int winner = 0;
        boolean callFlag = true;
        while (rounds <= SERVER.getTotalRounds()) {
            for (int i = 0; i < 3; i++) {
                RECORDS.get(i).clear();
            }
            if (callFlag) {
                // 当某一ClientThread发现都准备后解锁
                synchronized (LOCK) {
                    try {
                        LOCK.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
            for (int i = 0; i < 3; i++) {
                sendMessage("START@" + rounds, i, true);
                if (Server.getClients()[i] != null) {
                    Server.getClients()[i].setReady(false);
                }
            }
            ArrayList<Card> remainingCards = new ArrayList<>();
            for (String s : INIT_CARD) {
                remainingCards.add(new Card(s));
            }
            for (int i = 0; i < 3; i++) {
                CARDS_LIST.get(i).clear();
                for (int j = 0; j < 17; j++) {
                    int rand = RANDOM.nextInt(remainingCards.size());
                    CARDS_LIST.get(i).add(remainingCards.get(rand));
                    remainingCards.remove(rand);
                }
                CARDS_LIST.get(i).sort(Comparator.reverseOrder());            //服务端可以不用整理牌，这个东西到时候调到客户端
            }
            StringBuilder[] sbs = {new StringBuilder("CARD"), new StringBuilder("CARD"), new StringBuilder("CARD")};
            for (int i = 0; i < 3; i++) {
                for (Card card : CARDS_LIST.get(i)) {
                    sbs[i].append("@");
                    sbs[i].append(card.content());
                }
                sbs[i].append("@");
                sbs[i].append(PLAYER_LIST[i]);
            }
            for (int i = 0; i < 3; i++) {
                for (StringBuilder sb : sbs) {
                    sendMessage(sb.toString(), i, true);
                }
            }
            int[] call = new int[3];
            for (int i = 0; i < 3; i++) {
                int j = (winner + i) % 3;
                if (Server.getClients()[j] == null) {
                    waitingFor = j;
                    isPause = true;
                    try {
                        synchronized (LOCK) {
                            LOCK.wait();
                        }
                    } catch (InterruptedException e) {
                        throw new RuntimeException();
                    }
                }
                isPause = false;
                sendMessage("CALL?", j, true);
                try {
                    synchronized (LOCK) {
                        LOCK.wait();
                    }
                } catch (InterruptedException e) {
                    throw new RuntimeException();
                }
                RECORDS.get(j).remove("CALL?");
                call[j] = points;
                if (points == 3) {
                    break;
                }
            }
            if (call[0] != 0 || call[1] != 0 || call[2] != 0) {
                int landlord;
                int counter = 0;
                if (call[0] > call[1] && call[0] > call[2]) {
                    points = call[0];
                    landlord = 0;
                } else if (call[1] > call[0] && call[1] > call[2]) {
                    points = call[1];
                    landlord = 1;
                } else {
                    points = call[2];
                    landlord = 2;
                }
                CARDS_LIST.get(landlord).addAll(remainingCards);
                CARDS_LIST.get(landlord).sort(Comparator.reverseOrder());
                for (int i = 0; i < 3; i++) {
                    sendMessage("LANDLORD@" + points + "@" + landlord + "@" + remainingCards.get(0).content() + "@" + remainingCards.get(1).content() + "@" + remainingCards.get(2).content(), i, true);
                }
                if (SERVER.isAllowDouble()) {
                    needDouble = new int[]{-1, -1, -1};
                    for (int i = 0; i < 3; i++) {
                        sendMessage("DOUBLE?", i, true);
                    }
                    synchronized (LOCK) {
                        try {
                            LOCK.wait();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                    for (ArrayList<String> strList : RECORDS) {
                        strList.remove("DOUBLE?");
                    }
                }
                while (!CARDS_LIST.get(0).isEmpty() && !CARDS_LIST.get(1).isEmpty() && !CARDS_LIST.get(2).isEmpty()) {
                    if (Server.getClients()[(landlord + counter) % 3] == null) {
                        waitingFor = (landlord + counter) % 3;
                        isPause = true;
                        synchronized (LOCK) {
                            try {
                                LOCK.wait();
                            } catch (InterruptedException e) {
                                throw new RuntimeException(e);
                            }
                        }
                    }
                    isPause = false;
                    sendMessage("PLAY", (landlord + counter) % 3, true);
                    synchronized (LOCK) {
                        try {
                            LOCK.wait();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                    RECORDS.get((landlord + counter) % 3).remove("PLAY");
                    counter++;
                }
                for (int i = 0; true; i++) {
                    if (CARDS_LIST.get(i).isEmpty()) {
                        winner = i;
                        break;
                    }
                }
                if (winner == landlord) {
                    SCORES[landlord] += points * 2;
                    SCORES[(landlord + 1) % 3] -= points;
                    SCORES[(landlord + 2) % 3] -= points;
                } else {
                    SCORES[landlord] -= points * 2;
                    SCORES[(landlord + 1) % 3] += points;
                    SCORES[(landlord + 2) % 3] += points;
                }
                for (int i = 0; i < 3; i++) {
                    sendMessage("SCORE@" + SCORES[0] + "@" + SCORES[1] + "@" + SCORES[2], i, false);
                }
                callFlag = true;
                rounds++;
            } else {
                winner = (winner + 1) % 3;
                callFlag = false;
            }
        }
        Platform.runLater(() -> {
            CONTROLLER.name1.setText("");
            CONTROLLER.name2.setText("");
            CONTROLLER.name3.setText("");
            CONTROLLER.playerConfig.setDisable(false);
            CONTROLLER.gameConfig.setDisable(false);
            CONTROLLER.mainConfig.setDisable(false);
            CONTROLLER.start.setDisable(false);
            CONTROLLER.stop.setDisable(true);
        });
        SERVER.stopServer(false);
    }

    private void sendMessage(String message, int id, boolean record) {
        if (Server.getClients()[id] != null) {
            Server.getClients()[id].getWriter().println(message);
            Server.getClients()[id].getWriter().flush();
        }
        if (record) {
            RECORDS.get(id).add(message);
        }
    }

    public int getPoints() {
        return points;
    }

    public void setPoints(int points) {
        this.points = points;
    }

    public ArrayList<ArrayList<Card>> getCardsList() {
        return CARDS_LIST;
    }

    public int[] getNeedDouble() {
        return needDouble;
    }

    public int[] getScores() {
        return SCORES;
    }

    public ArrayList<ArrayList<String>> getRecords() {
        return RECORDS;
    }

    public int getWaitingFor() {
        return waitingFor;
    }

    public boolean isPause() {
        return isPause;
    }

    public boolean isInGame() {
        return isInGame;
    }

    public void setInGame(boolean inGame) {
        isInGame = inGame;
    }

    public String[] getPlayerList() {
        return PLAYER_LIST;
    }

    public int getRounds() {
        return rounds;
    }
}
